package pers.cj.pdos.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import pers.cj.pdos.constant.OrderType;
import pers.cj.pdos.controller.GoodsSnController;
import pers.cj.pdos.controller.entity.ResponseData;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.mapper.*;
import pers.cj.pdos.service.IInGoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.GoodsVo;
import pers.cj.pdos.vo.InGoodsGoodsVo;
import pers.cj.pdos.vo.InGoodsVo;
import pers.cj.pdos.vo.PayWaitVo;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author chenj
 * @since 2019-11-04
 */
@Service
public class InGoodsServiceImpl extends ServiceImpl<InGoodsMapper, InGoods> implements IInGoodsService {
    @Autowired
    InGoodsMapper inGoodsMapper;
    @Autowired
    InGoodsGoodsMapper inGoodsGoodsMapper;
    @Autowired
    GoodsSnMapper goodsSnMapper;
    @Autowired
    GoodsSnLogMapper goodsSnLogMapper;
    @Autowired
    GoodsStockMapper goodsStockMapper;
    @Autowired
    GoodsCostMapper goodsCostMapper;
    @Autowired
    HouseWaitInMapper houseWaitInMapper;
    @Autowired
    HouseWaitInGoodsMapper houseWaitInGoodsMapper;
    @Autowired
    InGoodsOrderGoodsMapper inGoodsOrderGoodsMapper;
    @Autowired
    InGoodsOrderMapper inGoodsOrderMapper;
    @Autowired
    PayWaitMapper payWaitMapper;
    @Autowired
    BorrowInMapper borrowInMapper;
    @Autowired
    BorrowInGoodsMapper borrowInGoodsMapper;
    @Autowired
    SettAccountMapper settAccountMapper;

    @Override
    public boolean checkNo(String no, String companyId) {
        return inGoodsMapper.selectCount(new QueryWrapper<InGoods>().eq("company_id",companyId).eq("no",no)) > 0;
    }




    @Override
    public List<InGoodsVo> listVo(String companyId,
                                  Integer page,
                                  Integer limit,
                                  Boolean close,
                                  String search,
                                  String no,
                                  String goodsName,
                                  String remark,
                                  String provider,
                                  Date makeTime1,
                                  Date makeTime2,
                                  String storeId,
                                  String userStoreId,
                                  String userId,
                                  Date date1,
                                  Date date2,
                                  Date date,
                                  String providerId,
                                  String houseId,
                                  String makeUserId) {
        return inGoodsMapper.listVo(companyId,
                Utils.genPage(page,limit),
                limit,
                null,
                close,
                search,
                no,
                goodsName,
                remark,
                provider,
                makeTime1,
                makeTime2,
                storeId,
                userStoreId,
                userId,
                date1,
                date2,
                date,
                providerId,
                houseId,
                makeUserId);
    }

    @Override
    public long count(String companyId,
                      Boolean close,
                      String search,
                      String no,
                      String goodsName,
                      String remark,
                      String provider,
                      Date makeTime1,
                      Date makeTime2,
                      String storeId,
                      String userStoreId,
                      String userId,
                      Date date1,
                      Date date2,
                      Date date,
                      String providerId,
                      String houseId,
                      String makeUserId) {
        return inGoodsMapper.count(companyId,
                null,
                close,
                search,
                no,
                goodsName,
                remark,
                provider,
                makeTime1,
                makeTime2,
                storeId,
                userStoreId,
                userId,
                date1,
                date2,
                date,
                providerId,
                houseId,
                makeUserId);
    }

    @Override
    public List<InGoodsVo> listVoForSelect(String companyId,
                                           Integer page,
                                           Integer limit,
                                           String storeId,
                                           String userStoreId,
                                           String userId,
                                           String search) {
        return inGoodsMapper.listVoForSelect(companyId,
                Utils.genPage(page,limit),
                limit,
                storeId,
                userStoreId,
                userId,
                search);
    }

    @Override
    public Long countForSelect(String companyId,
                               String storeId,
                               String userStoreId,
                               String userId,
                               String search) {
        return inGoodsMapper.countForSelect(companyId,
                storeId,
                userStoreId,
                userId,
                search);
    }

    @Override
    public InGoodsVo getVoById(String id) {
        return inGoodsMapper.getVoById(id);
    }

    @Override
    public List<InGoodsVo> listVoByIds(List<String> ids) {
        return inGoodsMapper.listVoByIds(ids);
    }

    @Override
    public void insert(BusinessSet businessSet, InGoods inGoods, List<InGoodsGoods> inGoodsGoodsList, List<GoodsSn> goodsSnList, List<GoodsSnLog> goodsSnLogList) {
        inGoodsMapper.insert(inGoods);
        inGoodsGoodsMapper.insertBatch(inGoodsGoodsList);

        InGoodsVo inGoodsVo = inGoodsMapper.getVoById(inGoods.getId());

        //余额-
        settAccountMapper.addBalance(inGoodsVo.getRealAmt().negate(), inGoodsVo.getSettAccountId());

        processPayWait(1, inGoodsVo);//欠款单处理

        //从进货订单发起的进货，需要同步处理进货订单
        processInGoodsOrder(1,inGoodsVo);

        if (!Utils.isEmpty(inGoodsVo.getBorrowInId())) {
            //由借入单转进货的话，就直接处理借入单就行，
            processBorrowIn(1, inGoodsVo);
            if (!Utils.isEmpty(goodsSnLogList)) {
                goodsSnLogMapper.insertBatch(goodsSnLogList);
            }
        } else {
            if (!PdosUtils.houseInOut(businessSet)) {
                //未启用出入库管理，直接添加库存
                processGoodsStock(1, inGoodsVo);
                if (!Utils.isEmpty(goodsSnList)) {
                    goodsSnMapper.insertBatch(goodsSnList);
                    goodsSnLogMapper.insertBatch(goodsSnLogList);
                }
            } else {
                //启用库存管理，则添加待入库单数据
                processHouseWaitIn(1, inGoodsVo);
            }
        }
    }



    @Override
    public void close(InGoods inGoods, BusinessSet businessSet) {
        InGoodsVo inGoodsVo = inGoodsMapper.getVoById(inGoods.getId());


        //余额+
        settAccountMapper.addBalance(inGoodsVo.getRealAmt(), inGoodsVo.getSettAccountId());

        processInGoodsOrder(2,inGoodsVo);

        //处理应付欠款
        processPayWait(2,inGoodsVo);

        if (!Utils.isEmpty(inGoodsVo.getBorrowInId())) {
            processBorrowIn(2,inGoodsVo);
            //改变该进货单对应的sn状态为0即 为关闭
            goodsSnLogMapper.updateBorrowByInGoodsId(inGoodsVo.getId(),0);
        } else {
            //直接入库的进货单，则需要去除相应的库存和sn。
            if (inGoodsVo.getStatus() == 1) {
                processGoodsStock(2, inGoodsVo);
                //关闭进货单对应的sn日志的borrow状态为0即 为关闭
                List<GoodsSn> list = PdosUtils.genGoodsSnList(inGoodsVo.getInGoodsGoodsVoList());
                if (!Utils.isEmpty(list)) {
                    goodsSnMapper.outByList(inGoodsVo.getHouseId(), list);
                }
            } else {
                processHouseWaitIn(2, inGoodsVo);
            }
        }

        InGoods temp = new InGoods();
        temp.setId(inGoods.getId());
        temp.setClose(true);
        inGoodsMapper.updateById(temp);
    }

    @Override
    public List<InGoodsVo> listVoByInGoodsOrder(String inGoodsOrderId) {
        return inGoodsMapper.listVoByInGoodsOrder(inGoodsOrderId);
    }

    @Override
    public List<InGoodsVo> listVoByBorrowInId(String borrowInId) {
        return inGoodsMapper.listVoByBorrowInId(borrowInId);
    }

    @Override
    public boolean checkClose(InGoods inGoods) {
        return inGoodsMapper.selectCount(new QueryWrapper<InGoods>().eq("id",inGoods.getId()).eq("close",true))  > 0;
    }

    @Override
    public boolean checkByInGoodsOrder(String inGoodsOrderId) {
        return inGoodsMapper.selectCount(new QueryWrapper<InGoods>().eq("in_goods_order_id",inGoodsOrderId).eq("close",false) ) > 0;
    }


    private void processBorrowIn(int type, InGoodsVo inGoodsVo){
        if (Utils.isEmpty(inGoodsVo.getBorrowInId())) {
            return;
        }

        List<BorrowInGoods> borrowInGoodsList = new ArrayList<>();
        for (InGoodsGoodsVo inGoodsGoodsVo :inGoodsVo.getInGoodsGoodsVoList()){
            BorrowInGoods entity = new BorrowInGoods();
            entity.setId(inGoodsGoodsVo.getBorrowInGoodsId());
            entity.setBorrowInId(inGoodsVo.getBorrowInId());
            entity.setGoodsId(inGoodsGoodsVo.getGoodsId());
            entity.setNumber(inGoodsGoodsVo.getNumber());
            entity.setInGoodsNumber(type==1 ? inGoodsGoodsVo.getNumber():inGoodsGoodsVo.getNumber().negate());
            entity.setHasNumber(new BigDecimal(0));
            entity.setWaitNumber(type==1 ? inGoodsGoodsVo.getNumber().negate():inGoodsGoodsVo.getNumber());
            entity.setUnitId(inGoodsGoodsVo.getUnitId());
            entity.setTimes(inGoodsGoodsVo.getTimes());
            entity.setPrice(inGoodsGoodsVo.getPrice());
            entity.setAmount(inGoodsGoodsVo.getAmount());
            entity.setCompanyId(inGoodsVo.getCompanyId());
            borrowInGoodsList.add(entity);
        }
        borrowInGoodsMapper.insertBatch(borrowInGoodsList);

        BorrowIn temp = new BorrowIn();
        temp.setId(inGoodsVo.getBorrowInId());

        long totalWaitInNumber = borrowInGoodsMapper.countWaitNumber(inGoodsVo.getBorrowInId());
        long number = borrowInGoodsMapper.countNumber(inGoodsVo.getBorrowInId());
        if(totalWaitInNumber > 0) {

            if (number == totalWaitInNumber){//未归还
                temp.setInStatus(1);
            } else {//部分归还
                temp.setInStatus(2);
            }
        } else {
            //全部归还
            temp.setInStatus(3);
        }
        borrowInMapper.updateById(temp);
    }

    private void processInGoodsOrder(int type, InGoodsVo inGoodsVo){
        if (Utils.isEmpty(inGoodsVo.getInGoodsOrderId())) {
            return;
        };

        List<InGoodsOrderGoods> inGoodsOrderGoodsList = new ArrayList<>();
        for (InGoodsGoodsVo inGoodsGoodsVo :inGoodsVo.getInGoodsGoodsVoList()){
            InGoodsOrderGoods vo = new InGoodsOrderGoods();
            vo.setId(inGoodsGoodsVo.getInGoodsOrderGoodsId());
            vo.setInGoodsOrderId(inGoodsVo.getInGoodsOrderId());
            vo.setGoodsId(inGoodsGoodsVo.getGoodsId());
            vo.setNumber(inGoodsGoodsVo.getNumber());
            vo.setHasInNumber(type==1 ? inGoodsGoodsVo.getNumber():inGoodsGoodsVo.getNumber().negate());
            vo.setWaitInNumber(type==1 ? inGoodsGoodsVo.getNumber().negate():inGoodsGoodsVo.getNumber());
            vo.setUnitId(inGoodsGoodsVo.getUnitId());
            vo.setTimes(inGoodsGoodsVo.getTimes());
            vo.setPrice(inGoodsGoodsVo.getPrice());
            vo.setAmount(inGoodsGoodsVo.getAmount());
            vo.setCompanyId(inGoodsVo.getCompanyId());
            inGoodsOrderGoodsList.add(vo);
        }

        inGoodsOrderGoodsMapper.insertBatch(inGoodsOrderGoodsList);


        InGoodsOrder temp = new InGoodsOrder();
        temp.setId(inGoodsVo.getInGoodsOrderId());

        long totalWaitInNumber = inGoodsOrderGoodsMapper.countWaitInNumber(inGoodsVo.getInGoodsOrderId());
        long number = inGoodsOrderGoodsMapper.countNumber(inGoodsVo.getInGoodsOrderId());
        if(totalWaitInNumber > 0) {
            //部分入库
            if (number == totalWaitInNumber){
                temp.setInStatus(1);
            } else {
                temp.setInStatus(2);
            }
            temp.setClose(false);
        } else {
            //全部入库
            temp.setInStatus(3);
            temp.setStatus(3);
            temp.setClose(true);
        }
        inGoodsOrderMapper.updateById(temp);
    }

    private void processPayWait(int type, InGoodsVo inGoodsVo) {
        if (inGoodsVo.getTotalAmt().compareTo(inGoodsVo.getRealAmt()) == 1) {
            //总计金额大于实付金额，此时产生欠款单
            PayWaitVo payWaitVo = payWaitMapper.getVoByProvider(inGoodsVo.getProviderId());
            if (payWaitVo == null) {
                if (type == 1) {
                    PayWait payWait = new PayWait();
                    payWait.setId(UuidUtils.getUUID());
                    payWait.setProviderId(inGoodsVo.getProviderId());
                    payWait.setCompanyId(inGoodsVo.getCompanyId());

                    BigDecimal total = inGoodsVo.getTotalAmt().subtract(inGoodsVo.getRealAmt());
                    payWait.setTotal(total);
                    payWait.setHasPay(new BigDecimal("0"));
                    payWait.setWaitPay(payWait.getTotal());
                    payWait.setDiscount(new BigDecimal("0"));
                    payWaitMapper.insert(payWait);
                }
            } else {
                BigDecimal total = inGoodsVo.getTotalAmt().subtract(inGoodsVo.getRealAmt());
                PayWait payWait = new PayWait();
                payWait.setId(payWaitVo.getId());
                if (type == 1) {
                    payWait.setTotal(total.add(payWaitVo.getTotal()));
                    payWait.setWaitPay(total.add(payWaitVo.getWaitPay()));
                } else {
                    payWait.setTotal(payWaitVo.getTotal().subtract(total));
                    payWait.setWaitPay(payWaitVo.getWaitPay().subtract(total));
                }
                if (payWait.getWaitPay().compareTo(new BigDecimal("0")) == 0) {
                    payWait.setWaitPay(new BigDecimal("0"));
                }
                payWaitMapper.updateById(payWait);
            }
        }
    }

    private void processHouseWaitIn(int type, InGoodsVo inGoodsVo) {
        if (type == 2) {
            HouseWaitIn houseWaitIn = new HouseWaitIn();
            houseWaitIn.setClose(true);
            houseWaitInMapper.update(houseWaitIn, new QueryWrapper<HouseWaitIn>().eq("in_goods_id", inGoodsVo.getId()));
            return ;
        }

        HouseWaitIn houseWaitIn = new HouseWaitIn();
        houseWaitIn.setId(UuidUtils.getUUID());
        houseWaitIn.setInGoodsId(inGoodsVo.getId());
        houseWaitIn.setHouseId(inGoodsVo.getHouseId());
        houseWaitIn.setClose(false);
        houseWaitIn.setStatus(1);//待入库
        houseWaitIn.setType(1);//设置类型为进货
        houseWaitIn.setCompanyId(inGoodsVo.getCompanyId());
        houseWaitIn.setTime(inGoodsVo.getTime());
        houseWaitInMapper.insert(houseWaitIn);

        List<HouseWaitInGoods> houseWaitInGoodsList = new ArrayList<>();
        for (InGoodsGoodsVo vo : inGoodsVo.getInGoodsGoodsVoList()) {
            HouseWaitInGoods houseWaitInGoods = new HouseWaitInGoods();
            houseWaitInGoods.setId(UuidUtils.getUUID());
            houseWaitInGoods.setHouseWaitInId(houseWaitIn.getId());
            houseWaitInGoods.setInGoodsGoodsId(vo.getId());
            houseWaitInGoods.setGoodsId(vo.getGoodsId());
            houseWaitInGoods.setHasInNumber(new BigDecimal("0"));
            houseWaitInGoods.setWaitInNumber(vo.getNumber());
            houseWaitInGoods.setNumber(vo.getNumber());
            houseWaitInGoods.setUnitId(vo.getUnitId());
            houseWaitInGoods.setTimes(vo.getTimes());
            houseWaitInGoods.setCompanyId(inGoodsVo.getCompanyId());
            houseWaitInGoodsList.add(houseWaitInGoods);
        }
        houseWaitInGoodsMapper.insertBatch(houseWaitInGoodsList);
    }


    /**
     * 库存处理
     * @param type 1.新增单据 2作废单据
     * @param inGoodsVo
     */
    private void processGoodsStock(int type, InGoodsVo inGoodsVo){
        List<GoodsCost> goodsCostList = new ArrayList<>();
        List<GoodsStock> goodsStockList = new ArrayList<>();
        for (InGoodsGoodsVo igv : inGoodsVo.getInGoodsGoodsVoList()) {
            BigDecimal number = igv.getNumber().multiply(igv.getTimes());
            BigDecimal amount = igv.getAmount();
            if (type == 2) {
                number = new BigDecimal("-"+number.toString());
                amount = new BigDecimal("-"+amount.toString());
            }
            //库存
            GoodsStock goodsStock = new GoodsStock();
            goodsStock.setId(UuidUtils.getUUID());
            goodsStock.setGoodsId(igv.getGoodsId());
            goodsStock.setHouseId(inGoodsVo.getHouseId());
            goodsStock.setNum(number); //数量*换算倍数
            goodsStock.setCompanyId(inGoodsVo.getCompanyId());
            goodsStockList.add(goodsStock);

            //成本
            GoodsCost goodsCost = new GoodsCost();
            goodsCost.setId(UuidUtils.getUUID());
            goodsCost.setGoodsId(igv.getGoodsId());
            goodsCost.setNumber(number);
            goodsCost.setTotalAmount(amount);
            goodsStock.setTime(new Date());
            goodsCost.setCompanyId(inGoodsVo.getCompanyId());
            goodsCostList.add(goodsCost);
        }

        goodsStockMapper.insertBatch(goodsStockList);
        goodsCostMapper.insertBatch(goodsCostList);



    }

}
